# -*- coding: utf-8 -*-
from odoo import models, fields, api
from odoo.exceptions import UserError
import logging

_logger = logging.getLogger(__name__)


class SyncLogReference(models.Model):
    """ 日志-业务记录关联中间模型 """
    _name = 'sync.log.reference'
    _description = '日志关联记录'

    # 添加数据库索引
    # 唯一约束确保不重复关联
    _sql_constraints = [
        ('unique_log_record',
         'unique(log_id, model_name, record_id)',
         '该记录已关联至日志!')
    ]

    # 日志记录关联
    log_id = fields.Many2one(
        'sync.log',
        string='日志记录',
        required=True,
        ondelete='cascade',
        index=True,
        help="关联的日志记录"
    )

    # 业务模型关联
    model_name = fields.Char('关联业务模型', required=True, index=True)
    record_id = fields.Integer('记录ID', required=True, index=True)

    # 新增计算字段
    display_name = fields.Char(
        string='记录名称',
        compute='_compute_display_name',
        store=True,         # 存储到数据库
        help="关联记录的显示名称"
    )

    # 计算显示名称
    @api.depends('model_name', 'record_id')
    def _compute_display_name(self):
        """优化版显示名称计算，解决新建记录缓存问题"""
        # 按模型分组处理（提升性能）
        model_groups = {}
        for ref in self:
            if ref.model_name not in model_groups:
                model_groups[ref.model_name] = []
            model_groups[ref.model_name].append(ref)

        # 批量查询每个模型的记录（使用sudo绕过权限检查）
        for model_name, refs in model_groups.items():
            try:
                # 检查模型是否存在
                if model_name not in self.env:
                    raise KeyError(f"模型 {model_name} 不存在")

                model = self.env[model_name].sudo()
                record_ids = [r.record_id for r in refs]

                # 批量查询并过滤已删除记录
                records = model.browse(record_ids).exists()
                name_mapping = {r.id: r.display_name for r in records}

                for ref in refs:
                    if ref.record_id in name_mapping:
                        ref.display_name = f"单号：{name_mapping[ref.record_id]}(分录ID：{model_name}-{ref.record_id})"
                    else:
                        # 添加详细调试信息
                        ref.display_name = f"待确认记录({model_name}-{ref.record_id})"
                        _logger.warning(
                            "记录不存在或权限不足 - 模型:%s ID:%s 操作人:%s",
                            model_name, ref.record_id, self.env.user.name
                        )

            except KeyError as e:
                _logger.error("模型不存在: %s", str(e))
                for ref in refs:
                    ref.display_name = f"无效模型({model_name})"
            except Exception as e:
                _logger.exception("显示名称计算异常")
                for ref in refs:
                    ref.display_name = f"计算错误({model_name}-{ref.record_id})"

    def _compute_open_button(self):
        """打开关联的业务记录（优化版）"""
        self.ensure_one()
        try:
            # 确保模型存在
            if self.model_name not in self.env:
                raise UserError(f"模型 '{self.model_name}' 不存在")

            # 确保记录存在
            record = self.env[self.model_name].browse(self.record_id)
            if not record.exists():
                raise UserError(f"记录 {self.record_id} 在模型 '{self.model_name}' 中不存在")

            return {
                'type': 'ir.actions.act_window',
                'name': record.display_name,
                'res_model': self.model_name,
                'res_id': self.record_id,
                'view_mode': 'form',
                'target': 'current',
                'context': {'create': False, 'edit': False}
            }
        except Exception as e:
            _logger.exception("打开关联记录失败")
            raise UserError(f"无法打开关联记录: {str(e)}")

    def open_related_record(self):
        """打开关联的业务记录"""
        self.ensure_one()
        try:
            # 确保模型存在
            if self.model_name not in self.env:
                raise UserError(f"模型 '{self.model_name}' 不存在")

            # 确保记录存在
            record = self.env[self.model_name].browse(self.record_id)
            if not record.exists():
                raise UserError(f"记录 {self.record_id} 在模型 '{self.model_name}' 中不存在")

            return {
                'type': 'ir.actions.act_window',
                'name': record.display_name,
                'res_model': self.model_name,
                'res_id': self.record_id,
                'view_mode': 'form',
                'target': 'current',
                'context': {'create': False, 'edit': False}
            }
        except Exception as e:
            raise UserError(f"无法打开关联记录: {str(e)}")

    log_ref_date = fields.Datetime(string='关联时间', default=fields.Datetime.now)
    log_ref_user = fields.Many2one('res.users', string='操作人', default=lambda self: self.env.user)


class SyncLog(models.Model):
    _name = 'sync.log'
    _description = '接口同步日志'
    _order = 'create_date desc'

    # 添加数据库索引
    _sql_constraints = [
        ('sync_time_idx', 'CREATE INDEX sync_time_idx ON sync_log (sync_time)', ''),
        ('log_level_idx', 'CREATE INDEX log_level_idx ON sync_log (log_level)', ''),
        ('user_id_idx', 'CREATE INDEX user_id_idx ON sync_log (user_id)', ''),
        ('model_name_idx', 'CREATE INDEX model_name_idx ON sync_log (model_name)', ''),
    ]

    # 核心字段
    sync_time = fields.Datetime('同步时间', default=fields.Datetime.now, index=True)  # 添加索引
    content = fields.Text('日志内容')
    log_level = fields.Selection([
        ('info', '信息'),
        ('warning', '警告'),
        ('error', '错误')
    ], string='日志级别', default='info', index=True)  # 添加索引
    user_id = fields.Many2one('res.users', '操作人', default=lambda self: self.env.user, index=True)  # 添加索引
    model_name = fields.Char('业务模型', index=True)  # 添加这个字段

    # 通过中间表关联业务模型
    reference_ids = fields.One2many(
        'sync.log.reference',
        'log_id',
        string='关联记录'
    )

    # 计算字段：动态显示关联记录
    reference_names = fields.Char(
        string='关联单据',
        compute='_compute_reference_names',
    )

    # 计算字段：关联模型列表
    reference_model = fields.Char(
        string="关联业务模型",
        compute="_compute_ref_model",
        store=False
    )

    @api.depends('reference_ids')
    def _compute_ref_model(self):
        """优化关联模型计算"""
        # 使用SQL查询提高性能
        query = """
                    SELECT log_id, ARRAY_AGG(DISTINCT model_name) AS models
                    FROM sync_log_reference
                    WHERE log_id IN %s
                    GROUP BY log_id
                """
        log_ids = tuple(self.ids)

        if not log_ids:
            return

        self.env.cr.execute(query, (log_ids,))
        results = dict(self.env.cr.fetchall())

        for log in self:
            log.reference_model = ", ".join(results.get(log.id, []))

    @api.depends('reference_ids')
    def _compute_reference_names(self):
        for log in self:
            names = []
            for ref in log.reference_ids:
                try:
                    model = self.env[ref.model_name]
                    record = model.browse(ref.record_id)
                    # 使用name_get方法获取显示名称
                    display_name = record.name_get()
                    if display_name:
                        names.append(f"{display_name[0][1]}({ref.model_name})")
                    else:
                        names.append(f"无效记录({ref.model_name}-{ref.record_id})")
                except:
                    names.append(f"无效记录({ref.model_name}-{ref.record_id})")
            log.reference_names = "; ".join(names) if names else "未关联记录"

    # =============== 新增动作方法 ===============
    def action_view_details(self):
        """查看关联业务记录的详情"""
        self.ensure_one()

        # 检查是否有关联记录
        if not self.reference_ids:
            raise UserError("当前日志未关联任何业务记录！")

        # 获取所有关联记录
        references = self.reference_ids

        # 准备动作参数
        action = {
            'type': 'ir.actions.act_window',
            'name': f'日志关联的业务记录',
            'view_mode': 'list,form',
            'context': {'create': False, 'delete': False},
        }

        # 处理不同模型关联记录
        if len(set(references.mapped('model_name'))) == 1:
            # 如果所有关联记录属于同一模型
            model_name = references[0].model_name
            record_ids = references.mapped('record_id')
            # 处理不同模型关联记录
            action.update({
                'res_model': model_name,
                'domain': [('id', 'in', record_ids)],
                'views': [(False, 'list'), (False, 'form')],
            })
        else:
            # 混合模型时使用中间视图
            action.update({
                'res_model': 'sync.log.reference',
                'domain': [('id', 'in', references.ids)],
                'views': [(False, 'list'), (False, 'form')],
                'context': {'group_by': 'model_name'},
            })

        return action

